package plus.easydo.utils.node;


import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author laoyu
 */
public class NodeUtils {

    private NodeUtils() {
    }

    /**
     * 递归获取所有子节点
     * @param root 父节点
     * @param allList 所有节点集合
     * @param pFunction 父节点关联标识
     * @param cFunction 子节点关联标识
     * @param operation 获取到子节点的子节点集合后的自定义操作
     * @param <T> 根节点、函数输入类型
     * @param <R> 函数返回类型
     * @return 子节点树集合
     */
    public static  <T,R> List<T> getChildrenList( T root, List<T> allList, Function<T,R> pFunction, Function<T,R> cFunction, CustomNodeFunction<T,List<T>> operation) {
        List<T> children;
        /*递归出所有子节点*/
        Stream<T> stream = allList.stream().filter(i -> pFunction.apply(root).equals(cFunction.apply(i)));
        children = stream.map(m->{
                    List<T> list = getChildrenList(m, allList, pFunction, cFunction, operation);
                    operation.operationChildNode(m,list);
                    return m;
                }
                )
                .collect(Collectors.toList());
        return children;
    }

    /**
     * 将集合转为树结构
     * @param predicate 判断是否为根节点的函数
     * @param allList 所有节点集合
     * @param pFunction 父节点关联标识
     * @param cFunction 子节点关联标识
     * @param operation 获取到子节点的子节点集合后的自定义操作
     * @param <T> 根节点、函数输入类型
     * @param <R> 函数返回类型
     * @return 所有节点树结构
     */
    public static <T,R> List<T> generateTree(List<T> allList, Predicate<? super T> predicate, Function<T,R> pFunction, Function<T,R> cFunction, CustomNodeFunction<T,List<T>> operation){
        /*筛选出所有父节点*/
        List<T> allParentList = allList.stream().filter(predicate).collect(Collectors.toList());
        /*循环遍历递构造所有节点树结构*/
       return allParentList.stream().map(p->{
            List<T> list = getChildrenList(p, allList, pFunction, cFunction, operation);
            operation.operationChildNode(p,list);
            return p;
        }).collect(Collectors.toList());
    }
}
